package com.example.springboot01.controller;


import com.example.springboot01.DTO.AccountDTO;
import com.example.springboot01.annotation.Permissions;
import com.example.springboot01.annotation.WithoutAuthorization;
import com.example.springboot01.config.ResultMsg;
import com.example.springboot01.config.ResultStatusEnum;
import com.example.springboot01.config.ServiceException;
import com.example.springboot01.model.Account;
import com.example.springboot01.params.AccountParams;
import com.example.springboot01.service.AccountService;
import com.example.springboot01.utils.ModelMapperUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;


/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author ruanzhihong
 * @since 2022-05-08
 */
@Api(value = "admin_account",tags = "用户后台（管理）")
@RestController
@RequestMapping("/admin/account")
public class AdminAccountController {


    @Autowired
    AccountService accountService;

    Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * @param accountParams 账户参数
     * @return 返回结果
     */
    @ApiOperation(value = "账户注册", notes = "根据账户参数创建一个账户记录")

    @WithoutAuthorization
    @ApiImplicitParam(name = "accountParams", value = "账户参数", required = true, dataType = "AccountParams")
    @PostMapping("/")
    public ResultMsg register(AccountParams accountParams) {
        try {
            //非空校验
            if (StringUtils.isBlank(accountParams.getUserName())) {
                return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, "账户姓名存在空值");
            }
            if (StringUtils.isBlank(accountParams.getPassword())) {
                return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, "账户密码存在空值");
            }
            if (StringUtils.isBlank(accountParams.getNickName())) {
                return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, "账户昵称存在空值");
            }
            if (StringUtils.isBlank(accountParams.getGender())) {
                return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, "账户性别存在空值");
            }
            if (StringUtils.isBlank(accountParams.getEmail())) {
                return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, "账户邮箱存在空值");
            }
            if (StringUtils.isBlank(accountParams.getTelephone())) {
                return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, "账户手机号码存在空值");
            }


            //参数类转实体类
            Account account = paramsToBean(accountParams);
            //调用服务层方法做保存
            accountService.save(account);
            //操作结果返回
            return ResultMsg.ok(ResultStatusEnum.SAVE_SUCCESS);
        } catch (ServiceException se) {
            logger.error("注册失败：" + se.getMsg());
            return ResultMsg.error(ResultStatusEnum.SAVE_ERROR, se.getMsg());
        } catch (Exception e) {
            logger.error(ExceptionUtils.getStackTrace(e));
            return ResultMsg.error(ResultStatusEnum.SAVE_ERROR);
        }
    }

    /**
     * 参数类转实体类
     *
     * @param accountParams 账户参数类对象
     * @return 实体类对象
     */
    private Account paramsToBean(AccountParams accountParams) {
        Account account = ModelMapperUtils.map(accountParams, Account.class);
        return account;
    }



    /**
     * 账户修改
     *
     * @param id            账户id
     * @param accountParams 账户参数
     * @return 返回结果
     */
    @ApiOperation(value = "账户编辑", notes = "根据账户id和账户属性更新账户记录")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "token字符串",required = true,dataType = "String",paramType = "header"),
            @ApiImplicitParam(name = "id", value = "账户id", required = true, dataType = "String"),
            @ApiImplicitParam(name = "accountParams", value = "账户参数", required = true, dataType = "AccountParams")
    })
    @Permissions(role = "admin")
    @PutMapping("{id}")
    public ResultMsg update(@PathVariable String id, @RequestBody AccountParams accountParams) {
        try {
            //校验用户id是否存在 todo
            if (accountService.getById(id) == null) {
                return ResultMsg.error(ResultStatusEnum.UPDATE_ERROR, "账户id不存在");
            }
            //参数类转实体类
            Account account = paramsToBean(accountParams);
            account.setId(id);
            account.setPassword(null);
            //调用服务层对象来更新用户
            accountService.updateById(account);
            //返回操作结果
            return ResultMsg.ok(ResultStatusEnum.UPDATE_SUCCESS);

        } catch (ServiceException se) {
            logger.error("账户编辑失败：" + se.getMsg());
            return ResultMsg.error(ResultStatusEnum.UPDATE_ERROR, se.getMsg());
        } catch (Exception e) {
            logger.error(ExceptionUtils.getStackTrace(e));
            return ResultMsg.error(ResultStatusEnum.UPDATE_ERROR);
        }
    }

    /**
     * 获取账户信息
     *
     * @param id 账户id
     * @return 账户Dto
     */

    @ApiOperation(value = "获取账户", notes = "根据账户id获取账户信息")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "token字符串",required = true,dataType = "String",paramType = "header"),
            @ApiImplicitParam(name = "id", value = "账户id", required = true, dataType = "String")
    })
    @Permissions(role = "admin")
    @GetMapping("{id}")
    public ResultMsg<AccountDTO> get(@PathVariable String id) {

        try {
            //校验用户id是否存在
            if (accountService.getById(id) == null) {
                return ResultMsg.error(ResultStatusEnum.UPDATE_ERROR, "账户id不存在");
            }
            //调用服务层方法获取账户，如果查询结果为空，则返回错误
            Account account = accountService.getById(id);
            if (account == null) {
                return ResultMsg.error(ResultStatusEnum.SELECT_ERROR, "无此账户");
            }
            //实体类转DTO类
            AccountDTO accountDTO = beanToDTO(account);
            //返回结果给前端
            return ResultMsg.ok(accountDTO);
        } catch (ServiceException se) {
            logger.error("获取账户失败：" + se.getMsg());
            return ResultMsg.error(ResultStatusEnum.SELECT_ERROR, se.getMsg());
        } catch (Exception e) {
            logger.error(ExceptionUtils.getStackTrace(e));
            return ResultMsg.error(ResultStatusEnum.SELECT_ERROR);
        }
    }




    /**
     * 删除账户
     * @param id 账户id
     * @return 操作结果
     */
    @ApiOperation(value = "删除账户",notes = "根据账户id删除账户")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "token字符串",required = true,dataType = "String",paramType = "header"),
            @ApiImplicitParam( name = "id" ,value = "账户id" ,required = true ,dataType = "String")
    })
    @Permissions(role = "admin")
    @DeleteMapping("{id}")
    public ResultMsg delete(@PathVariable String id){
        try {
            //校验用户id是否存在 todo
            if (accountService.getById(id) == null) {
                return ResultMsg.error(ResultStatusEnum.DELETE_ERROR, "账户id不存在");
            }
            //调用服务层方法获取账户，如果查询结果为空，则返回错误
            if (!accountService.removeById(id)){
                return ResultMsg.error(ResultStatusEnum.DELETE_ERROR,"删除账户失败");
            }
            //返回结果给前端
            return ResultMsg.ok(ResultStatusEnum.DELETE_SUCCESS);
        } catch (ServiceException se) {
            logger.error("删除账户失败：" + se.getMsg());
            return ResultMsg.error(ResultStatusEnum.DELETE_ERROR, se.getMsg());
        } catch (Exception e) {
            logger.error(ExceptionUtils.getStackTrace(e));
            return ResultMsg.error(ResultStatusEnum.DELETE_ERROR);
        }
    }

    @ApiOperation(value = "多条件查询",notes = "根据指定条件查询账户列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "token",value = "token字符串",required = true,dataType = "String",paramType = "header"),
            @ApiImplicitParam(name = "name" , value = "用户姓名" ,required = false ,dataType = "String"),
            @ApiImplicitParam(name = "nickName" , value = "用户昵称" ,required = false ,dataType = "String"),
            @ApiImplicitParam(name = "gender" , value = "用户性别" ,required = false ,dataType = "String"),
            @ApiImplicitParam(name = "telephone" , value = "用户手机号码" ,required = false ,dataType = "String"),
            @ApiImplicitParam(name = "email" , value = "用户邮箱" ,required = false ,dataType = "String"),
            @ApiImplicitParam(name = "image" , value = "用户头像" ,required = false ,dataType = "String"),
            @ApiImplicitParam(name = "current" , value = "开始页码" ,required = true ,dataType = "String"),
            @ApiImplicitParam(name = "size" , value = "每页数量" ,required = true ,dataType = "String")
    })
    @Permissions(role = "admin")
    @GetMapping("/")
    public ResultMsg<List<AccountDTO>> list(@RequestParam (required = false) String name,
                                            @RequestParam (required = false) String nickName,
                                            @RequestParam (required = false ,defaultValue = "MAN") String gender,
                                            @RequestParam (required = false) String telephone,
                                            @RequestParam (required = false) String email,
                                            @RequestParam (required = false) String image,
                                            @RequestParam Integer current,
                                            @RequestParam Integer size
    ){
        try {
            //根据参数构造实体类
            Account account = new Account(name,nickName,gender,telephone,email,image);

            //调用服务层方法做查询
            List<Account> accountList = accountService.listByParams(account,current,size);
            //如果返回列表为空，那么则返回错误信息
            if (accountList == null || accountList.isEmpty()) {
                return ResultMsg.error(ResultStatusEnum.SELECT_ERROR, "查无账户");
            }
            //把账户s实体类列表转成DTO列表
            List<AccountDTO> dtoList = beanListToDTOList(accountList);
            //返回结果

            return ResultMsg.ok(dtoList);
        }catch (ServiceException se) {
            logger.error("查询账户列表失败：" + se.getMsg());
            return ResultMsg.error(ResultStatusEnum.SELECT_ERROR, se.getMsg());
        } catch (Exception e) {
            logger.error(ExceptionUtils.getStackTrace(e));
            return ResultMsg.error(ResultStatusEnum.SELECT_ERROR);
        }
    }



    /**
     * 实体类转DTO类
     * @param account
     * @return
     */
    private AccountDTO beanToDTO(Account account) {
        return ModelMapperUtils.map(account,AccountDTO.class);
    }

    /**
     * 账户实体类列表转DTO类
     * @param accountList  实体类列表
     * @return  DTO列表
     */
    private List<AccountDTO> beanListToDTOList(List<Account> accountList) {
        List<AccountDTO> dtoList = ModelMapperUtils.mapList(accountList,AccountDTO.class);
        return dtoList;
    }
}